import { parseDocument } from "htmlparser2";
import { compact } from "lodash-es";
import type { INode } from "../lib/types";

export class NodeParser {
    public nodeTree: INode[] = [];

    constructor(html: string) {
        const parser = parseDocument(html);
        this.nodeTree = parser.children.map(this.getNode.bind(this)).filter((node): node is INode => node !== undefined);
    }

    getNode(node: any): INode | undefined {
        const children = node.children ?? [];
        // 指令 v-for
        const vFor = node.attribs?.["v-for"] ?? "";
        // 指令 v-if
        const vIf = node.attribs?.["v-if"] ?? "";

        const condition: {
            type: string;
            value: string;
        }[] = [];

        if (vFor) {
            condition.push({ type: "v-for", value: vFor });
        }
        if (vIf) {
            condition.push({ type: "v-if", value: vIf });
        }

        // 先去除 Text 节点
        if (node.name === undefined && (node.data.trim() === "\n" || node.data.trim() === "")) {
            return undefined;
        }

        return {
            tag: node.name,
            className: node?.attribs?.class ?? "",
            style: node?.attribs?.style ?? "",
            child: compact(children.map(this.getNode.bind(this))),
            isComponent: false,
            condition,
            data: node.data,
        };
    }
}


export class NodeRender {
    constructor(private node: INode) {

    }

    static valReg = /{{(.*?)}}/g;

    // 处理赋值
    private handleData(node: INode, inData: any) {
        // 处理节点 style data className 中使用到的变量
        if (node.data) {
            node.data = node.data.replace(NodeRender.valReg, (match, p1) => {
                const val = inData[p1];
                return val;
            });
        }

        if (node.style) {
            node.style = node.style.replace(NodeRender.valReg, (match, p1) => {
                const val = inData[p1];
                return val;
            });
        }

        if (node.className) {
            node.className = node.className.replace(NodeRender.valReg, (match, p1) => {
                const val = inData[p1];
                return val;
            });
        }
    }

    render(inData: any) {
        const node = this.node;
        const children = node.child;
        const className = node.className;
        const style = node.style;
        const data = node.data;

        // 处理赋值
        this.handleData(node, inData);

        // 处理子节点
        children.forEach((child) => {
            this.handleData(child, inData);
        });

        return node;
    }
}

